/*******************************************************
 *
 *  Switch Routines for EECE 494, Assignment 2.
 *
 *  Created by _________, University of British Columbia
 *
 *  This is where you will put your routines to implement
 *  the switch routines.  You should use the headers as
 *  supplied.  All your code for Assignment 2 will go in this
 *  file (and possibly in switch.h)
 *
 ******************************************************/

#include "defs.h"

// The BAD implementation just for comparison.

void *switch_thread_routine(void *arg)
{
   /* Add your code here */
   
	while(!die)
	{
		int i;
		for(i = 0; i < 4; i++)
		{
			port_lock(&in_port[i]);
			if(in_port[i].flag)
			{
				// Copy packet
				packet_t *packet = (packet_t*) malloc(sizeof(packet_t));
				packet_copy(&in_port[i].packet, packet);
				in_port[i].flag = FALSE;
				port_unlock(&in_port[i]);
				
				int dst_port = cam_lookup_address(&(packet->address));
				
				// Write out
				// Check if port is ready to be written to
				while(1)
				{
					port_lock(&out_port[dst_port]);
					if(out_port[dst_port].flag)
					{
						port_unlock(&out_port[dst_port]);
						usleep(100000);
						continue;
					}
					break;
				}
				packet_copy(packet, &out_port[dst_port].packet);
				out_port[dst_port].flag = TRUE;
				port_unlock(&out_port[dst_port]);
				
				free(packet);
			}
			else
			{
				port_unlock(&in_port[i]);
			}
		}
		usleep(100000);
	}
	
}

void switch_init()
{
   /* Add your code here.  At the very least, you probably
      want to include a call to cam_init() */
	cam_init();
}

void switch_add_entry(ip_address_t *address,
                      int port)
{
   /* Add your code here.  It might be as simple as adding
      a call to cam_add_entry() */
	cam_add_entry(address, port);
}

void switch_free()
{
   /* add your code (if any) here */
}
